package org.example.gamemodel;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class World {
    public int id;
    public List<String> players=new ArrayList<>();
    public Map<String, Socket> player_sockets=new HashMap<>();
    public int frame_id=0;
    public JSONObject real_time_frame=new JSONObject();
    public JSONArray frames=new JSONArray();
    public Map<String,Integer> player_lost_connect_time=new HashMap<>();

    ExecutorService executorService= Executors.newFixedThreadPool(4);

    public World(int id){
        this.id=id;
        real_time_frame.put("frame_num",frame_id);
        real_time_frame.put("frame",new JSONObject());

        //定时任务
        new Thread(new Runnable() {
            @Override
            public void run() {
                log("启动定时任务");
                while(true){
                    TimedTask();
                    try {
                        Thread.sleep(15);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }).start();

        //检查玩家失联时间
        new Thread(new Runnable() {
            @Override
            public void run() {
                log("启动失联检查线程");
                while(true) {
                    try {
                        Thread.sleep(1000);
                        for (String player : player_lost_connect_time.keySet()) {
                            int sec = player_lost_connect_time.get(player);
                            if (sec > 4) {
                                log(player + "失联.");
                                delPlayer(player);
                                player_lost_connect_time.remove(player);
                                break;
                            } else {
                                player_lost_connect_time.put(player, sec + 1);
                            }
                        }
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }catch (ConcurrentModificationException e){
                        log(e.toString());
                    }
                }
            }
        }).start();
    }

    public void addPlayer(String player,Socket player_socket){
        players.add(player);
        player_sockets.put(player,player_socket);
    }

    public void delPlayer(String player){
        log("delect player "+player);
        players.remove(player);
        try {
            if(player_sockets.get(player)!=null) {
                player_sockets.get(player).close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        player_sockets.remove(player);
        ((JSONObject)real_time_frame.get("frame")).remove(player);
    }

    public void SendFrame(String user,JSONObject frame){
        if(players.contains(user)){
            ((JSONObject)real_time_frame.get("frame")).put(user,frame);
            player_lost_connect_time.put(user,0);
        }
    }

    public void ReLink(String user,Socket socket){
        log(user+"重新连接.");
        player_sockets.put(user,socket);
    }

    public void TimedTask(){
        try {
            for(Socket socket:player_sockets.values()){
                JSONObject jsonObject=new JSONObject();
                jsonObject.put("action","frame_sync");
                jsonObject.put("real_time_frame",real_time_frame);
//                log(real_time_frame.toJSONString());
                PrintWriter printWriter=new PrintWriter(socket.getOutputStream());
                printWriter.print(jsonObject.toJSONString());
                printWriter.flush();
//                System.out.println("to "+socket+":"+real_time_frame.toJSONString());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    void log(String msg){
        System.out.println("[World_"+id+"]"+msg);
    }
}
